﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Web;
using System.Text.RegularExpressions;

namespace Core.HTTPModules
{
    public class RedirectionCollection : ConfigurationElementCollection
    {
        public override ConfigurationElementCollectionType CollectionType
        {
            get
            {
                return ConfigurationElementCollectionType.AddRemoveClearMap;
            }
        }

        public RedirectionElement this[int index]
        {
            get { return (RedirectionElement)BaseGet(index); }
            set
            {
                if (BaseGet(index) != null)
                    BaseRemoveAt(index);
                BaseAdd(index, value);
            }
        }

        public void Add(RedirectionElement element)
        {
            BaseAdd(element);
        }


        public void Clear()
        {
            BaseClear();
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new RedirectionElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((RedirectionElement)element).TargetUrl;
        }
    }

    public class RedirectionElement : ConfigurationElement
    {
        public RedirectionElement() { }

        public RedirectionElement(string title, string description)
        {
            this.TargetUrl = title;
            this.DestinationUrl = description;
        }

        [ConfigurationProperty("targetUrl", IsRequired = true)]
        public string TargetUrl
        {
            get { return (string)this["targetUrl"]; }
            set { this["targetUrl"] = value; }
        }

        [ConfigurationProperty("destinationUrl", IsRequired = false, DefaultValue = "/")]
        public string DestinationUrl
        {
            get { return (string)this["destinationUrl"]; }
            set { this["destinationUrl"] = value; }
        }

        public Regex UrlRegex;
    }

    public class RedirectionGroup : ConfigurationSection
    {
        [ConfigurationProperty("redirections", IsDefaultCollection = false),
        ConfigurationCollection(typeof(RedirectionCollection), AddItemName = "add")]
        public RedirectionCollection Redirections
        {
            get { return this["redirections"] as RedirectionCollection; }
        }
    }

    public class HTTPRedirect : IHttpModule
    {
        private string applicationPath;
        private RedirectionGroup redirectionsList;

        public HTTPRedirect()
        {
            applicationPath = (HttpRuntime.AppDomainAppVirtualPath.Length > 1) ? HttpRuntime.AppDomainAppVirtualPath : String.Empty;
        }

        #region IHttpModule Members
        /// <summary>
        /// Initializes the module, and registers for application events.
        /// </summary>
        /// <param name="context">
        /// The System.Web.HttpApplication instance exposing application events.
        /// </param>
        public void Init(HttpApplication context)
        {
            redirectionsList = ConfigurationManager.GetSection("redirectionGroup") as RedirectionGroup;

            if (redirectionsList != null)
            {
                foreach (RedirectionElement redirection in redirectionsList.Redirections)
                {
                    string targetUrl;

                    targetUrl = redirection.TargetUrl.ToLower();
                    targetUrl = HandleTilde(targetUrl);
                    redirection.UrlRegex = new Regex(targetUrl);
                }
            }

            context.BeginRequest += new EventHandler(context_BeginRequest);
        }

        void context_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication app;
            string requestUrl;

            app = sender as HttpApplication;

            if (redirectionsList != null && redirectionsList.Redirections.Count > 0)
            {
                foreach (RedirectionElement redirection in redirectionsList.Redirections)
                {
                    requestUrl = app.Request.RawUrl.ToLower();

                    if (redirection.UrlRegex.IsMatch(requestUrl))
                    {
                        string destinationUrl;

                        destinationUrl = HandleTilde(redirection.DestinationUrl);

                        app.Response.Clear();
                        app.Response.StatusCode = 301;
                        app.Response.StatusDescription = "Moved Permanently";
                        app.Response.AddHeader("Location", destinationUrl);
                        app.Response.End();

                        break;
                    }
                }
            }
        }

        /// <summary>
        /// Disposes of the resources (other than memory) used by the module.
        /// </summary>
        public void Dispose()
        {

        }

        #endregion

        #region Private methods
        private string HandleTilde(string url)
        {
            if ((url == null) || (url.Length < 1))
                return url;

            if (url.StartsWith("^~/"))
                return "^" + applicationPath + url.Substring("^~/".Length - 1);
            else if (url.StartsWith("~/"))
                return applicationPath + url.Substring("~/".Length - 1);
            return url;
        }
        #endregion
    }

}
